package com.qsl;

import org.python.core.PyBoolean;
import org.python.core.PyException;
import org.python.core.PyFloat;
import org.python.core.PyFunction;
import org.python.core.PyInteger;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.util.PythonInterpreter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


public class JythonExecutor {

    /**
     * 编辑python脚本
     * @param script python脚本
     */
    public static void scriptCompile(String script) {
        // 初始化 Python 解释器
        PythonInterpreter interpreter = new PythonInterpreter();
        try {
            // 编译脚本
            interpreter.exec(script);
            getFunction(interpreter);
        } catch (PyException e) {
            throw new RuntimeException("函数脚本编译错误：" + e.getMessage());
        }
    }

    /**
     * 执行python脚本
     * @param executeModel 函数体与参数
     * @param params 参数值
     * @return
     */
    public static Object scriptExecute(PythonFuncModel executeModel, Map params) {
        // 初始化 Python 解释器
        PythonInterpreter interpreter = new PythonInterpreter();

        try {
            // 编译脚本
            interpreter.exec(executeModel.getScript());
            PyFunction function = getFunction(interpreter);
            // 函数类型转换
            PyObject result = function.__call__(executeModel.getParams().stream()
                    .map(p -> {
                        if (p.getRuleAttrType() == 1) {
                            return convertToPython(p.getType(), params.get(p.getValue()));
                        } else {
                            return convertToPython(p.getType(), p.getValue());
                        }
                    }).toArray(PyObject[]::new));
            return convertToJava(executeModel.getReturnType(), result);
        } catch (PyException e) {
            throw new RuntimeException("函数脚本执行错误：" + e.getMessage());
        }
    }

    public static Object scriptExecute(PythonFuncModel executeModel) {
        // 初始化 Python 解释器
        PythonInterpreter interpreter = new PythonInterpreter();

        try {
            // 编译脚本
            interpreter.exec(executeModel.getScript());
            PyFunction function = getFunction(interpreter);
            // 函数类型转换
            PyObject result = function.__call__(executeModel.getParams().stream()
                    .map(p -> convertToPython(p.getType(), p.getValue()))
                    .toArray(PyObject[]::new));
            return convertToJava(executeModel.getReturnType(), result);
        } catch (PyException e) {
            throw new RuntimeException("函数脚本执行错误：" + e.getMessage());
        }
    }

    private static PyFunction getFunction(PythonInterpreter interpreter) {
        // 获取所有全局变量
        PyObject globals = interpreter.getLocals();
        // 查找函数并验证
        List<PyFunction> functions = new ArrayList<>();
        for (PyObject key : globals.asIterable()) {
            PyObject value = globals.__finditem__(key);
            if (value instanceof PyFunction) {
                functions.add((PyFunction) value);
            }
        }
        // 保证脚本代码中只有一个方法
        if (functions.size() != 1) {
            throw new RuntimeException("函数脚本中方法只能是一个");
        }
        return functions.get(0);
    }

    public static Object stringToObject(int type, String value) {
        Object result = null;
        switch (type) {
            case 3:
                result = Integer.parseInt(value);
                break;
            case 5:
                result = Float.parseFloat(value);
                break;
            case 6:
                result = Double.parseDouble(value);
                break;
            case 8:
                result = Boolean.parseBoolean(value);
                break;
            case 9:
                result = value;
                break;
        }
        return result;
    }

    public static PyObject convertToPython(int type, Object value) {
        PyObject result = null;
        switch (type) {
            case 3:
                result = new PyInteger((int) value);
                break;
            case 5:
                result = new PyFloat((float) value);
                break;
            case 6:
                result = new PyFloat((double) value);
                break;
            case 8:
                result = new PyBoolean((boolean) value);
                break;
            case 9:
                result = new PyString((String) value);
                break;
            default:
                throw new RuntimeException("数据类型 " + type + " 不能转换成Python类型");
        }
        return result;
    }

    public static Object convertToJava(int type, PyObject value) {
        Object result = null;
        switch (type) {
            case 3:
                result = Integer.parseInt(value.__str__().toString());
                break;
            case 5:
                result = Float.parseFloat(value.__str__().toString());
                break;
            case 6:
                result = Double.parseDouble(value.__str__().toString());
                break;
            case 8:
                result = Boolean.parseBoolean(value.__str__().toString());
                break;
            case 9:
                result = (String) value.__str__().toString();
                break;
            default:
                throw new RuntimeException("数据类型 " + type + " 不能转换成Java类型");
        }
        return result;
    }
}
